/* eslint-disable no-unused-vars */
/* eslint-disable no-self-assign */
/*
      ------分数注意事项-----
      本次测试满分为100(最多100分), 有4道加分题; 答案不够完整或者有错误当题0分处理;

      ------分数处理-----
      (0-60]: 不及格, 处理: 提供第二份不同试卷晚自习的时候重新考试, 并在第二天晚自习时间单独进行测试题提问(大部分都回答不上则采用手抄试卷方案);

      (60-75]: 良良, 处理: 晚自习时间单独进行测试题提问(大部分都回答不上则采用手抄试卷方案);

      (75-90]: 良好, 处理: 放你一马, 好好复习;

      (90-100]: 优秀, 处理: 好好好, 继续保持;
      */
// 1.JS延迟加载的方式有哪些？（5）

// 1.addEventListener("onload",function(){}) 这种方法是对页面的元素、标签、资源加载完后再进行加载js，避免元素资源加载过慢而导致js出错，
// 一般是运用在写代码时script脚本写在页面标签之前
// 2.setTimeout(function(){},time) 这个为延时定时器，在time（单位：ms/毫秒）时间后才执行回调函数function内的代码，只执行一次
// 3.setInterval（function(){},time) 这个为间歇定时器，在每隔time（单位：ms/毫秒）时间后再执行回调函数function内的代码，
// 这种方式可执行多次直至定时器关闭，当这个定时器规定只执行一次的时候，就能够达到js的延迟加载

// 2.前端 JavaScript 中的 ECMAScript、DOM、BOM 的含义；（5）
// ECMAScript ECMAScript是ECMA组织制定的一套规则，使用来规定在js中代码的标准
// DOM 全称文档对象模型（document object model），在一个html页面中有许多元素，每个元素可以称为一个节点，html可以看成是一个DOM树，
// 当我需要查找到某一个节点时，就是根据当前的节点位于DOM树的位置去获取，获取后可以对节点绑定事件
// BOM 全称浏览器对象模型（document object model），BOM是附属于浏览器的内容，不同于DOM，DOM是对html页面的元素进行处理，
// 而BOM是对浏览器进行处理，例如浏览器上的导航栏、工具栏等

// 4.如何进行数据类型的判断？（5）

// 1.typeof + 数据
//   "typeof+数据" 返回的是一个字符串，对于基本数据类型大部分可以准确返回其类型（除了null，返回的是Object），对于对象、数组类型一律返回Object
//     方法函数返回function
// 2.A instanceof B
//   "A instanceof B" 使用来判断数据A的数据类型是否与B相同，返回的是一个布尔值，相同返回的是true，不相同则返回false
//     这里的A为数据，B为数据类型的构造函数，但是数组 instanceof Object返回的是true
// 3.Object.prototype.toString.call(数据)
//   "Object.prototype.toString.call(数据)" 是根据数据调用对象中的原型方法去判断该数据的类型，返回的是一个[Object 数据类型]

// 5.null 和 undefined 的区别？什么时候会得到 undefined？（5）
// undefined是对于变量未定义，而null是对变量的指针指向空
// 1.当声明变量后未对其赋值，计算机会自动将其赋值为undefined
// 2.当function(){}中没有写明返回值的时候，默认返回undefined
// 3.当访问未声明的变量时，会报错“xxx is not defined”

// 6.如何理解 null == undefined 返回 true，null === undefined 返回 false？（5）
// "=="是对于判断数据的值是否相等，在用到比较运算符的时候，会将数据类型隐式转换成数字类型，这里的null和undefined都转化为数字0，所以"null==undefined"返回true
// "==="是对于判断数据的值和类型时候相等，在用到"==="的时候，只有两边的数据一模一样的时候才会返回true，所以"null===undefined"返回false

// 7.使用 continue 或 break 终止循环时，两种方式的区别是？（5）

// continue 是对于当前的循环进行中断，然后进入到下一次的循环中
// break 是对于整个循环的中断，break后直接跳出整个循环

// 8.如何判断字符串内是否包含指定字符？（5）
// 1.字符串1.indexOf("字符串2")
// 使用"字符串1.indexOf("字符串1")" 是判断字符串1是否含有字符串2的内容，有则返回字符串2在字符串1出现的开始下标，没有则返回-1
// 2.字符串1.lastIndexOf("字符串2")
// 使用"字符串1.indexOf("字符串1")"在判断字符串从头到尾的是否包含另一个字符串的时候用法与"字符串1.indexOf("字符串1")"一样
let str1 = '123456789';
let str2 = '0';
let str3 = '5';
console.log(str1.indexOf(str2)); //返回-1，
console.log(str1.indexOf(str3)); //返回4

// 9.请尽量列举出数组的方法，并且注明哪些方法会修改原数组，哪些不会；（5）
// concat() 数组的拼接，返回一个新数组，不会修改原数组
// join("分隔符") 数组转字符串,字符串之间会用"分隔符分开"
// splice(a,b,c) 将数组进行修改/添加/删除操作，会修改原数组
// slice(startIndex，endIndex) 将数组截取从开始下标截取到结束下标（如果没有默认截取到最后），返回新数组，不会修改原数组
// push\pop\shift\unshift 对数组进行（从数组最后添加/从数组最后删除/从数组开头删除/从数组开头添加），会修改原数组
// forEach(function(item,index,arr){}) 对数组遍历,没有返回值，不会修改原数组
// map(function(item,index,arr){}) 对数组遍历后，可以对数组进行操作，可以返回新数组，不会修改原数组
// includes("数据") 对数组进行遍历，查找数组中是否包含"数据",不会修改原数组
// every(function(item,index,arr){}) 对数组进行遍历，对数组每一个元素进行判断是否符合条件，都符合返回true，有一个不符合返回false，不会修改原数组
// some(function(item,index,arr){}) 对数组进行遍历，对数组每一个元素进行判断是否符合条件，有一个符合返回true，都不符合返回false，不会修改原数组
// reduce(function(total,item,index){},init) 对数组进行遍历，可以对数组的每一个元素操作后加入到total中来实现累加器的效果，不会修改原数组
// sort(function(a,b){}) 对数组按照一定的规则进行排序，不会修改原数组

// 10. 请写出下面语句的输出结果：（5）
// let bar = true, number = 0;
// console.log(bar + 0);        1
// console.log(bar + "xyz");    truexyz
// console.log(bar + true);     2
// console.log(+true);          1
// console.log(!'bluej');       false
// console.log(number++);       0
// console.log(++number);       2
// console.log(number);         2

// 11. 根据用户输入时间实现倒计时，输入时间格式错误时要有错误提示（5）
// window.prompt("请输入目标时间");
let button11 = document.querySelector('button');
button11.addEventListener('click', function () {
    let t = new Date(
        window.prompt('请输入目标时间（格式为：xxxx xx xx xx:xx:xx）')
    ).getTime(); //目标时间的时间戳
    if (typeof time != 'number') {
        alert('请输入正确时间格式');
    } else {
        daojishi(t);
    }
});
let q11 = document.querySelector('.q11');
function daojishi(t) {
    t = t;
    let timer = setInterval(function () {
        let nowTime = new Date().getTime(); //当前时间的时间戳
        let diff = Math.floor(t - nowTime) / 1000; //相差时间秒数
        if (diff < 0) {
            q11.innerHTML = '时间已过';
            return;
        } else {
            let second =
                Math.floor(diff % 60) < 10
                    ? '0' + Math.floor(diff % 60)
                    : Math.floor(diff % 60);
            let min =
                Math.floor(diff / 60) % 60 < 10
                    ? '0' + (Math.floor(diff / 60) % 60)
                    : Math.floor(diff / 60) % 60;
            let hour =
                Math.floor(diff / 60 / 60) % 24 < 10
                    ? '0' + (Math.floor(diff / 60 / 60) % 24)
                    : Math.floor(diff / 60 / 60) % 24;
            let date =
                Math.floor(diff / 60 / 60 / 24) < 10
                    ? '0' + Math.floor(diff / 60 / 60 / 24)
                    : Math.floor(diff / 60 / 60 / 24);
            // console.log(
            //   `离目标时间还有：${date}天${hour}小时${min}分钟${second}秒`
            // );
            q11.innerHTML = `离目标时间还有：${date}天${hour}小时${min}分钟${second}秒`;
        }
    }, 1000);
}
// 12.输出从小到大排序好的五个不重复的随机"素数",范围[10-58)；（10）
// 质数也叫素数是指在大于1的自然数中，除了1和它本身以外不再有其他因数的自然数，不能被任何整数整除的数。

function getRandom(m, n) {
    return Math.floor(Math.random() * (n - m) + m);
}
function findNum(n) {
    for (let i = 1; i <= 5; i++) {
        let num = getRandom(10, 58); //获取[10,58)的随机数
    }
}
findNum(5);
// 13.把下面数组成员排序打乱；（5）
let arr13 = [10, 20, 30, 40, 50, 60];
let newArr2 = []; // 打乱之后的数组
function getRandom1(arr) {
    return Math.floor(Math.random() * arr.length);
}
function mix(arr1, arr2) {
    let oldLength = arr1.length; //记录原始数组长度
    for (let i = 0; i < oldLength; i++) {
        let num = getRandom1(arr1); //随机获取下标,根据数组长度变化
        arr2.push(arr1[num]);
        arr1.splice(num, 1);
    }
    console.log(arr2);
}
mix(arr13, newArr2);

// 14. 将多个数组进行去重合并；（10）
let arr140 = [1, 2, 3],
    arr141 = [2, 3, 4, 5];
function quchong(arr1, arr2) {
    let newArr = arr1.concat(arr2);
    console.log(newArr);
    let newArr2 = [];
    for (let i = 0; i < newArr.length; i++) {
        if (
            newArr2.every(function (item, index) {
                return item != newArr[i];
            })
        ) {
            newArr2.push(newArr[i]);
        }
    }
    console.log(newArr2);
}
quchong(arr140, arr141);

// 15. 找出数组 arr=[1, 2, 3, "a", 4, "a", 2, 4, "a"] 中重复出现过的元素,并用数组将重复元素装起来输出,并且统计每个元素出现的次数（10）

let arr15 = [1, 2, 3, 'a', 4, 'a', 2, 4, 'a'];
let obj = {};
arr15.forEach(function (item, index, arr15) {
    if (obj[item]) {
        obj[item]++;
    } else {
        obj[item] = 1;
    }
    if (index === arr15.length - 1) {
        for (const k in obj) {
            if (obj[k] === 1) delete obj[k];
        }
        console.log(obj);
    }
});

// 16. 找出数组中年龄小于18岁的女生的信息重新组成新的数组,并且将她们count变为现有的平方（10）
let arr16 = [
    {
        name: '111',
        sex: 'boy',
        age: 18,
        count: 20,
    },
    {
        name: '222',
        sex: 'girl',
        age: 17,
        count: 30,
    },
    {
        name: '333',
        sex: 'boy',
        age: 16,
        count: 40,
    },
    {
        name: '444',
        sex: 'girl',
        age: 15,
        count: 50,
    },
    {
        name: '555',
        sex: 'boy',
        age: 20,
        count: 60,
    },
    {
        name: '666',
        sex: 'girl',
        age: 13,
        count: 70,
    },
    {
        name: '777',
        sex: 'boy',
        age: 14,
        count: 80,
    },
];
let newArr16 = arr16
    .filter(function (item, index) {
        return item.age < 18;
    })
    .map(function (item) {
        item.count *= item.count;
        return item;
    });
console.log(newArr16);

// 17. 实现一个深克隆函数 (加分题 5)
let obj17 = {
    a: 1,
    b: [1, 2, 3],
    c: { a: 1 },
    d: function () {
        console.log('123');
    },
};
let newObj17 = {};
function cloneDeep(obj) {
    let res;
    if (Object.prototype.toString.call(obj).slice(8, -1) == 'Array') {
        res = [];
    } else if (Object.prototype.toString.call(obj).slice(8, -1) == 'Object') {
        res = {};
    }
    for (const k in obj) {
        if (obj[k] instanceof Object) {
            res[k] = cloneDeep(obj[k]);
        } else {
            res[k] = obj[k];
        }
    }
    return res;
}
newObj17 = cloneDeep(obj17);
console.log(newObj17);

// 18. 实现一个数组的reduce方法 (加分题 5)
// 实现数组值的累加
let arr18 = [1, 2, 3, 4, 5, 6];
let sum = arr18.reduce(function (total, item, index) {
    return (total += item);
}, 0);
console.log(sum);

// 19. 写出强制转换的方法有哪些 (加分题 5)
// Number() 强制转换成number类型
// String() 强制转换成string类型
// toString() 只有在对象下可以使用
// Boolean() 强制转换成布尔类型

// 20. 如何判断一个对象是否为空对象的3种方法 (加分题 5)
